package com.kexio.auth.context;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 租户上下文持有者
 * 使用ThreadLocal管理当前线程的租户信息
 * 
 * @author Kexio Team
 * @since 1.0.0
 */
public class TenantContextHolder {
    
    private static final Logger logger = LoggerFactory.getLogger(TenantContextHolder.class);
    
    public static final String DEFAULT_TENANT_ID = "default";
    
    private static final ThreadLocal<String> TENANT_CONTEXT = new ThreadLocal<>();
    private static final ThreadLocal<TenantInfo> TENANT_INFO_CONTEXT = new ThreadLocal<>();
    
    /**
     * 设置当前租户ID
     */
    public static void setCurrentTenantId(String tenantId) {
        if (tenantId != null) {
            TENANT_CONTEXT.set(tenantId);
            logger.debug("设置租户上下文: tenantId={}", tenantId);
        } else {
            TENANT_CONTEXT.remove();
            logger.debug("清除租户上下文");
        }
    }
    
    /**
     * 获取当前租户ID
     */
    public static String getCurrentTenantId() {
        return TENANT_CONTEXT.get();
    }
    
    /**
     * 设置当前租户信息
     */
    public static void setCurrentTenantInfo(TenantInfo tenantInfo) {
        if (tenantInfo != null) {
            TENANT_INFO_CONTEXT.set(tenantInfo);
            // 同时设置租户ID
            if (tenantInfo.getTenantId() != null) {
                setCurrentTenantId(tenantInfo.getTenantId());
            }
            logger.debug("设置租户信息上下文: {}", tenantInfo);
        } else {
            TENANT_INFO_CONTEXT.remove();
            logger.debug("清除租户信息上下文");
        }
    }
    
    /**
     * 获取当前租户信息
     */
    public static TenantInfo getCurrentTenantInfo() {
        return TENANT_INFO_CONTEXT.get();
    }
    
    /**
     * 清理租户上下文
     */
    public static void clearTenantContext() {
        TENANT_CONTEXT.remove();
        TENANT_INFO_CONTEXT.remove();
        logger.debug("已清理租户上下文");
    }
    
    /**
     * 检查是否存在租户上下文
     */
    public static boolean hasTenantContext() {
        return TENANT_CONTEXT.get() != null;
    }
    
    /**
     * 获取租户ID，如果不存在则返回默认值
     */
    public static String getTenantIdOrDefault(String defaultTenantId) {
        String tenantId = getCurrentTenantId();
        return tenantId != null ? tenantId : defaultTenantId;
    }
    
    // ==================== 兼容性方法 ====================
    
    /**
     * 设置租户（兼容方法）
     */
    public static void setTenant(String tenantId) {
        setCurrentTenantId(tenantId);
    }
    
    /**
     * 获取租户（兼容方法）
     */
    public static String getTenant() {
        return getCurrentTenantId();
    }
    
    /**
     * 获取租户或null（兼容方法）
     */
    public static String getTenantOrNull() {
        return getCurrentTenantId();
    }
    
    /**
     * 清理上下文（兼容方法）
     */
    public static void clear() {
        clearTenantContext();
    }
    
    /**
     * 规范化租户ID
     */
    public static String normalizeTenantId(String tenantId) {
        if (tenantId == null || tenantId.trim().isEmpty()) {
            return DEFAULT_TENANT_ID;
        }
        
        // 移除特殊字符，只保留字母数字和下划线
        String normalized = tenantId.trim().toLowerCase().replaceAll("[^a-z0-9_]", "_");
        
        // 确保不为空
        if (normalized.isEmpty()) {
            return DEFAULT_TENANT_ID;
        }
        
        // 确保以字母开头
        if (!Character.isLetter(normalized.charAt(0))) {
            normalized = "tenant_" + normalized;
        }
        
        return normalized;
    }
    
    /**
     * 验证租户ID
     */
    public static boolean validateTenantId(String tenantId) {
        if (tenantId == null || tenantId.trim().isEmpty()) {
            return false;
        }
        
        String trimmed = tenantId.trim();
        
        // 检查长度
        if (trimmed.length() < 1 || trimmed.length() > 50) {
            return false;
        }
        
        // 检查格式：只允许字母、数字、下划线、中划线
        return trimmed.matches("^[a-zA-Z0-9_-]+$");
    }
    
    /**
     * 在指定租户上下文中执行操作
     */
    public static <T> T executeWithTenant(String tenantId, java.util.concurrent.Callable<T> action) throws Exception {
        String originalTenantId = getCurrentTenantId();
        try {
            setCurrentTenantId(tenantId);
            return action.call();
        } finally {
            if (originalTenantId != null) {
                setCurrentTenantId(originalTenantId);
            } else {
                clearTenantContext();
            }
        }
    }
    
    /**
     * 在指定租户上下文中执行操作（无返回值）
     */
    public static void executeWithTenant(String tenantId, Runnable action) {
        String originalTenantId = getCurrentTenantId();
        try {
            setCurrentTenantId(tenantId);
            action.run();
        } finally {
            if (originalTenantId != null) {
                setCurrentTenantId(originalTenantId);
            } else {
                clearTenantContext();
            }
        }
    }
    
    /**
     * 租户信息内部类
     */
    public static class TenantInfo {
        private String tenantId;
        private String tenantName;
        private String tenantCode;
        private Boolean enabled;
        private String description;
        
        public TenantInfo() {}
        
        public TenantInfo(String tenantId, String tenantName) {
            this.tenantId = tenantId;
            this.tenantName = tenantName;
        }
        
        // Getters and Setters
        public String getTenantId() { return tenantId; }
        public void setTenantId(String tenantId) { this.tenantId = tenantId; }
        
        public String getTenantName() { return tenantName; }
        public void setTenantName(String tenantName) { this.tenantName = tenantName; }
        
        public String getTenantCode() { return tenantCode; }
        public void setTenantCode(String tenantCode) { this.tenantCode = tenantCode; }
        
        public Boolean getEnabled() { return enabled; }
        public void setEnabled(Boolean enabled) { this.enabled = enabled; }
        
        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }
        
        @Override
        public String toString() {
            return "TenantInfo{" +
                    "tenantId='" + tenantId + '\'' +
                    ", tenantName='" + tenantName + '\'' +
                    ", tenantCode='" + tenantCode + '\'' +
                    ", enabled=" + enabled +
                    ", description='" + description + '\'' +
                    '}';
        }
    }
}